const fs = require('fs');
const path = require('path');
const JavaScriptObfuscator = require('javascript-obfuscator');
const bn = require('bytenode');

// 定义项目的入口文件路径，注意保持正确的大小写
const entryFileName = 'Index.js';
const distDir = path.join(__dirname, './dist');


// 递归获取所有 .js 文件的函数
function getAllJsFiles(dir) {
  let files = [];

  function recurse(currentDir) {
    const entries = fs.readdirSync(currentDir, { withFileTypes: true });

    for (const entry of entries) {
      const fullPath = path.join(currentDir, entry.name);
      if (entry.isDirectory()) {
        recurse(fullPath); // 递归进入子目录
      } else if (entry.isFile() && path.extname(entry.name).toLowerCase() === '.js') {
        files.push(fullPath);
      }
    }
  }

  recurse(dir);
  return files;
}


async function replaceImports(files) {
  for (const filePath of files) {
    try {
      // 读取文件内容
      let content = fs.readFileSync(filePath, 'utf8');

      // 获取相对路径以确定是否为入口文件
      const relativePath = path.relative(distDir, filePath);
      // 使用正确的正则表达式来匹配 require 后跟的字符串参数
      // 并确保替换后的内容正确
      content = content.replace(/require\(['"]((\.\.\/|\.\/)+[^'"\.\s]*?)(\.js)?['"]\)/g, "require('$1.jsc')");

      if (relativePath == 'Frame\\RouteBase.js') {
        //路由需要特殊处理
        content = content.replace(/require\(`(\${path\}\/\${fileName})`\)/g, "require(`$1.jsc`)");//替换强路由的路径
      }

      if (relativePath == entryFileName) {
        // 如果是入口文件，(需要顶部加) require('bytenode');
        content = `require('bytenode');\n${content}`;
      }

      // 混淆代码
      const obfuscatedCode = JavaScriptObfuscator.obfuscate(content, {
        compact: true,
        controlFlowFlattening: true
      }).getObfuscatedCode();

      // 将更新后的内容写回文件
      fs.writeFileSync(filePath, obfuscatedCode);
      console.log(`替换为jsc路径引入-并混淆: ${relativePath}`);
    } catch (error) {
      console.error(`处理文件时发生错误: ${filePath}`, error);
    }
  }
}

// // 获取所有需要处理的 .js 文件
const jsFiles = getAllJsFiles(distDir);
// 调用函数以替换导入路径
replaceImports(jsFiles)
  .then(() => {
    // 步骤 3：使用 bytenode 编译 JavaScript 文件为字节码，跳过入口文件
    jsFiles.forEach((filePath, index) => {

      // 只有在不是入口文件的情况下才编译为 .jsc
      if (!String(filePath).startsWith(path.join(distDir, entryFileName))) {
        const fileParse = path.parse(filePath);
        const outPath = path.join(fileParse.dir, `${fileParse.name}.jsc`);
        bn.compileFile({
              filename: filePath,
              output: outPath,
              compileAsModule: true
            });
        fs.unlinkSync(filePath); // 可选：编译完成后删除原始 .js 文件
        console.log(`[${index + 1}/${jsFiles.length}]编译成jsc字节码: ${filePath}`);


      } else {
        console.log(`[${index + 1}/${jsFiles.length}]跳过入口文件: ${filePath}`);
      }
    });

    console.log('构建和字节码编译完成。');
  }).catch(error => {
    console.error('过程失败:', error);
  });